#include "Watcher.h"

Watcher::Watcher()
{
//    QObject::connect(&m_timer, SIGNAL(timeout()), this, SLOT(checkEvent()));

    connect(&m_tcpSocket, SIGNAL(connected()), this, SLOT(sendNotify()));
    connect(&m_tcpSocket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(displayError(QAbstractSocket::SocketError)));

    QNetworkConfigurationManager manager;
    if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired) {
        // Get saved network configuration
        QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
        settings.beginGroup(QLatin1String("QtNetwork"));
        const QString id = settings.value(QLatin1String("DefaultNetworkConfiguration")).toString();
        settings.endGroup();

        // If the saved network configuration is not currently discovered use the system default
        QNetworkConfiguration config = manager.configurationFromIdentifier(id);
        if ((config.state() & QNetworkConfiguration::Discovered) !=
                QNetworkConfiguration::Discovered) {
            config = manager.defaultConfiguration();
        }

        networkSession = new QNetworkSession(config, this);
        connect(networkSession, SIGNAL(opened()), this, SLOT(sessionOpened()));

        networkSession->open();
    }

    int port = 36542;
    m_tcpSocket.abort();
    m_tcpSocket.connectToHost(ipAddress() /*"dmg-home.no-ip.info"*/, port, QIODevice::WriteOnly);
}

QString Watcher::ipAddress() const
{
    QString ipAddress;
    QList<QHostAddress> ipAddressesList = QNetworkInterface::allAddresses();
    // use the first non-localhost IPv4 address
    for (int i = 0; i < ipAddressesList.size(); ++i) {
        if (ipAddressesList.at(i) != QHostAddress::LocalHost &&
                ipAddressesList.at(i).toIPv4Address()) {
            ipAddress = ipAddressesList.at(i).toString();
            break;
        }
    }
    // if we did not find one, use IPv4 localhost
    if (ipAddress.isEmpty()) {
        ipAddress = QHostAddress(QHostAddress::LocalHost).toString();
    }
    return ipAddress;
}

void Watcher::sendNotify()
{
    qDebug() << "sendNotify";
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_4_0);

    Event event(EventString("20110708", "YYYYMMDD"));
    event.setName("some transferred event");

    out << (quint16)0;
    out << event;
    out.device()->seek(0);
    out << (quint16)(block.size() - sizeof(quint16));

    m_tcpSocket.write(block);
    m_tcpSocket.flush();
    //m_tcpSocket.waitForBytesWritten(20);
    m_tcpSocket.disconnectFromHost();
}

void Watcher::displayError(QAbstractSocket::SocketError socketError)
{
    switch (socketError) {
    case QAbstractSocket::RemoteHostClosedError:
        break;
    case QAbstractSocket::HostNotFoundError:
        qDebug() << tr("Watcher")
                 << tr("The host was not found. Please check the "
                       "host name and port settings.");
        break;
    case QAbstractSocket::ConnectionRefusedError:
            qDebug() << tr("Watcher")
                     << tr("The connection was refused by the peer. "
                           "Make sure the notify server is running, "
                           "and check that the host name and port "
                           "settings are correct.");
        break;
    default:
            qDebug() << tr("Watcher")
                     << tr("The following error occurred: %1.")
                        .arg(m_tcpSocket.errorString());
    }
}

void Watcher::sessionOpened()
{
    // Save the used configuration
    QNetworkConfiguration config = networkSession->configuration();
    QString id;
    if (config.type() == QNetworkConfiguration::UserChoice) {
        id = networkSession->sessionProperty(QLatin1String("UserChoiceConfiguration")).toString();
    } else {
        id = config.identifier();
    }

    QSettings settings(QSettings::UserScope, QLatin1String("Trolltech"));
    settings.beginGroup(QLatin1String("QtNetwork"));
    settings.setValue(QLatin1String("DefaultNetworkConfiguration"), id);
    settings.endGroup();
}

void Watcher::start()
{
    m_events = EventSchedule::getNotifySchedule(QDate::currentDate());
    m_timer.start(1000);
}

bool Watcher::checkEvent()
{
    if (m_events.count() == 0) {
        qDebug() << "no events";
        return false;
    }

    qDebug() << "event number:" << m_events.count();

    if (!m_notifiedEvents.isEmpty()) {
        return false;
    }

    foreach (const Event &event, m_events) {
        if (event.begin() <= QDateTime::currentDateTime()) {
            qDebug() << "EVENT BEGIN!\n" <<  event;
            m_notifiedEvents.append(event);
        }
    }
    return true;
}
